package mymyoux.io.mserverconnectorClasses
{
	import mymyoux.core.IObject;
	import mymyoux.debug.Log;
	import mymyoux.events.MAdvSocketEvent;
	import mymyoux.io.MSocket;
	import mymyoux.utils.StringUtils;
	/**
	 * MAdvSocket permet de créer un Socket dont la gestion est simplifiée. La classe est prévue pour fonctionner sur un MServer.
	 * @author Mymyoux
	 * @version 2.0
	 */
	public class MAdvSocket extends MSocket implements IMAdvSocket
	{
		/**
		 * Fixe la taille à laquelle sont découpées les morceaux de textes envoyés si ceux-ci sont trop grands.
		 */
		protected const CUT:int=500;
		/**
		 * @private
		 */
		protected var _id:uint;
		/**
		 * Le mot de passe nécessaire à l'identification sur un MServer.
		 */
		protected var _password:String;
		/**
		 * Permet de stocker les données découpées en attendant de pouvoir les recoller.
		 */
		protected var _tampon:Tampon; //utile si les messages sont trop gros!!
		/**
		 * Crée un objet MAdvSocket.
		 * @param	ip	L'ip du MServeur.
		 * @param	port	Le port du MServeur.
		 * @param	password	Mot de passe nécessaire à l'identification sur le MServer.
		 */
		 
		public function MAdvSocket(ip:String,port:uint,password:String=""){
			_id=0;
			_tampon=new Tampon();
			//définis dans MSOcket
			_ip=ip;
			_port=port;
			_password=password;
		}
		/**
		 * Id du joueur.
		 */
		public function get id():uint{
			return _id;
		}
		/**
		 * @inheritDoc 
		 */
		public function get ip():String{
			return _ip;
		}
		/**
		 * @inheritDoc 
		 */
		public function get port():uint{
			return _port;
		}
		/**
		 * @inheritDoc 
		 */
		public function get password():String{
			return _password;
		}
		/**
		 * Permet de se connecter au serveur.
		 * @param	ip	Inutile (pour la compatibilité)
		 * @param port	Inutile	(pour la compatibilité)
		 */
		public override function start(ip:String="",port:uint=0):void{
			send("i"+_password);
			super.start(_ip,_port);
		}
		/**
		 * Permet de se reconnecter au serveur.
		 */
		public override function restart():void{
			super.restart();
		}
		/**
		 * Permet d'envoyer du texte sur le serveur.
		 * @param	data Texte à envoyer.
		 */
		public function send(data:String):void{
			data=data.replace(/\\/g,"\\\\").replace(/]\[/g,"]\\[");
			if(data.substring(0,1)=="s"){
				var msg:Array=new Array();
				var nb:uint=uint(Number(data.substring(1,data.indexOf(":"))));
				var roomName:String="";
				if(nb>0 && data.length>nb+2){//supérieur à taille du nom de salon + s + :
								roomName=data.substring(data.indexOf(":")+1,data.indexOf(":")+nb+1);
				}
				if(roomName.length>0){
					data=data.substring(data.indexOf(":")+nb+1);
					if(data.length>3*CUT){
						var nbpart:int=-1;
						for(var i:int=0;i<data.length;i+=CUT){
							nbpart++;
						}
						
						for(i=0;i<data.length;i+=CUT){
							msg.push("part"+i/CUT+"/"+nbpart+"/"+data.substring(i,i+CUT));
						}
					}else{
						msg.push(data);
					}
					for(i=0;i<msg.length;i++){
						data=msg[i];
						data=data.replace(/\\/g,"\\\\").replace(/]\[/g,"]\\[");
						_send("[s"+nb+":"+roomName+data+"]");
					}
				}
			}else{
				data="["+data+"]";
				_send(data);
			}
		}
		/**
		 * Appelée lors de la réception de données.
		 * @param data Donnée reçue.
		 */
		protected override function onData(data:String):void{
			var tab:Array=data.substring(1,data.length-1).split("][");
			var roomName:String="",msg:String="";
			var nb:uint=0;
			for(var str:String in tab){
				str=tab[str].replace(/]\\\[/g,"][").replace(/\\\\/g,"\\");//allow ][ reading
				if(str.length>0){
					try{
						Log.show("[Réception : "+str+"]");
						var salon:String;
						var fct:String=str.substring(0,1);
						str=str.substring(1);
						//donne l'idx
						if(fct=="i"){
							_id=StringUtils.toNumber(str) as uint;
							this.dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.IDENTIFIED,str,_id));
						}
						//liste des personnes présentes dans un salon
						if(fct=="t"){
							if(str.indexOf(":")>0){
								var liste:Array=str.substring(0,str.indexOf(":")).split(",");
								salon=str.substring(str.indexOf(":")+1);
								if(liste.length>0 && salon.length>0){
								/*	for(var i:String in liste){
										dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.NEW_CONNECTED,liste[i],StringUtils.toNumber(liste[i])));
										dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.NEW_CONNECTED+salon,liste[i],StringUtils.toNumber(liste[i])));
									}*/
									dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.LIST,salon+":"+liste.toString()));
									dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.LIST+salon,liste.toString()));
								}
							}
						}
						var id:int;
						//arrivée d'une personne dans un salon
						if(fct=="g"){
							if(str.indexOf(":")>0){
								id=StringUtils.toNumber(str.substring(0,str.indexOf(":"))) as int;
								salon=str.substring(str.indexOf(":")+1);
								if(salon.length>0 && id>0){
									dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.NEW_CONNECTED,salon+":"+id.toString(),id));
									dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.NEW_CONNECTED+salon,id.toString(),id));
								}
							}
						}
						//sortie d'une personne d'un salon
						if(fct=="l"){
							if(str.indexOf(":")>0){
								id=StringUtils.toNumber(str.substring(0,str.indexOf(":"))) as int;
								salon=str.substring(str.indexOf(":")+1);
								if(salon.length>0 && id>0){
									dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.LOST_CONNECTED,salon+":"+id.toString(),id));
									dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.LOST_CONNECTED+salon,id.toString(),id));
								}
							}
						}
						//arrivée d'info
						if(fct=="c"){
							/*var tableau:Array=str.substring(2,str.length-2).split("§§§§");
							if(tableau.length>0){
								for(var i:int=0;i<tableau.length-1;i+=2){
									var tab2:Array=tableau[i+1].split("§§");
									
								}
							}*/
							var tableau:Array=str.substring(2,str.length-2).split("§§§§");
								for(var i:int=0;i<tableau.length-1;i+=2){
									dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.GET_INFO,"§§"+tableau[i+1]+"§§",StringUtils.toNumber(tableau[i]) as uint));
									//trace(MServerIdentifier.unserialize("§§"+tableau[i+1]+"§§"));
									
								}
						}
						if(fct=="s"){
							Log.show(str);
							nb=uint(Number(str.substring(0,str.indexOf(":"))));
							if(nb>0 && str.length>nb+2){//supérieur à taille du nom de salon + s + :
								roomName=str.substring(str.indexOf(":")+1,str.indexOf(":")+nb+1);
								if(roomName.length>0){
									str=str.substring(str.indexOf(":")+nb+1);
									if(str.indexOf(":")>-1){
										nb=uint(Number(str.substring(0,str.indexOf(":"))));
										if(nb>0){
											msg=str.substring(str.indexOf(":")+1);
											if(msg.length>0){
												if(msg.substring(0,4)=="part"){
													try{
														var actual:uint=uint(Number(msg.substring(4,msg.indexOf("/"))));
														var maximal:uint=uint(Number(msg.substring(msg.indexOf("/")+1,msg.indexOf("/",msg.indexOf("/")+1))));
														if(actual>=0 && maximal>=actual && maximal>0){
															
															if((msg=_tampon.add(nb,actual,maximal,msg.substring(msg.indexOf("/",msg.indexOf("/")+1)+1)))!=null){
																dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.DATA+roomName,msg,nb));
															}	
														}
													}catch(e:Error){
														
													}
												}else{
													
													dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.DATA+roomName,msg,nb));
												}
											}
										}
									}
								}
							}
						}
					}catch(e:Error){
						trace("Problème réception : "+e);
					}
				}
			}
		}
		/**
		 * 
		 * Permet de tester l'égalité entre 2 MAdvServers.
		 * @param	o	L'objet implémentant l'interface <code class="prettyprint">IObject</code> dont on souhaite tester l'égalité.
		 * @return	<code class="prettyprint">true</code> SI les 2 objets ont la même ip, utilise le même port et transmettent le même mot de passe. <code class="prettyprint">false</code> sinon.
		 */
		public override function equals(o:IObject):Boolean{
			try{
				var p:IMAdvSocket=o as IMAdvSocket;
				if(p.ip==_ip && p.password==_password && p.port==_port){
					return true;
				}
			}catch(e:Error){
			
			}
			return false;
		}
		/**
		 * Appelée lors de la connexion au MServer.
		 * Dispatch cet évènements aux écouteurs.
		 */
		protected override function onConnect():void{
			dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.CONNECT,null,0));
			//return true;
		}
		/**
		 * Appelée lors d'une erreur de la connexion au MServer.
		 * Dispatch cet évènements aux écouteurs.
		 */
		protected override function onError():void{
			dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.ERROR,null,0));
		}
		/**
		 * Appelée lors de la fermeture de la connexion au MServer.
		 * Dispatch cet évènements aux écouteurs.
		 */
		protected override function onClose():void{
			send("[i"+_password+"]");
			dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.CLOSE,null,0));
		}
		/**
		 * Convertit l'objet en String.
		 * @return	Une chaîne de caractères de la forme <code class="prettyprint">[ClasseObject paramètre1="valeur1" paramètre2="valeur2" ... ]</code> 
		 */
		public override function toString():String{
			return "[MAdvSocket ip=\""+_ip+"\" port=\""+_port+"\" password=\""+_password+"\"]";
		}
	}
}
internal class Tampon{
	private var _a:Array;
	public function Tampon(){
		_a=new Array();
	
	}
	public function add(idx:uint,actual:uint,maximal:uint,msg:String):String{
		 if(actual==0 || _a[idx]==null){
		 	_a[idx.toString()]="";
//		 	Alert.show(idx+" "+maximal);
		 }
		 trace(msg);
		 _a[idx.toString()]+=msg;
		 var value:String=null;
		 if(actual==maximal){
		 	value=_a[idx.toString()];
		 	_a[idx.toString()]=null;
		 }
		return value;
	}
}